package com.movie.service.impl;

import com.movie.dto.ReviewDTO;
import com.movie.dto.SystemUserDTO;
import com.movie.entity.Review;
import com.movie.entity.Comment;
import com.movie.entity.SysUser;
import com.movie.repository.ReviewRepository;
import com.movie.repository.CommentRepository;
import com.movie.repository.SystemUserRepository;
import com.movie.service.ReviewService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class ReviewServiceImpl implements ReviewService {

    private final ReviewRepository reviewRepository;
    private final CommentRepository commentRepository;

    private final SystemUserRepository userRepository;

    @Override
    public Page<ReviewDTO> findPendingReviews(String type, String source, Pageable pageable) {
        log.info("获取待审核列表, type: {}, source: {}", type, source);

        // 先查询所有评论，再按审核状态过滤（无审核记录视为 pending）
        List<Comment> allComments = commentRepository.findAll();
        List<Long> commentIds = allComments.stream().map(Comment::getId).collect(Collectors.toList());

        List<Review> reviews = commentIds.isEmpty() ? List.of() : reviewRepository.findByCommentIds(commentIds);
        java.util.Map<Long, Review> reviewByCommentId = reviews.stream()
                .collect(Collectors.toMap(r -> r.getComment().getId(), r -> r, (a, b) -> a));

        List<ReviewDTO> pendingList = new java.util.ArrayList<>();
        for (Comment c : allComments) {
            Review r = reviewByCommentId.get(c.getId());
            if (r == null) {
                // 无审核记录，视为待审核，手动构造 DTO
                ReviewDTO dto = new ReviewDTO();
                dto.setId(null);
                dto.setStatus("pending");
                dto.setCommentId(c.getId());
                dto.setCommentContent(c.getContent());
                dto.setCommentRating(c.getRating());
                dto.setCreatedAt(c.getCreatedAt());
                if (c.getMovie() != null) {
                    dto.setMovieId(c.getMovie().getId());
                    dto.setMovieTitle(c.getMovie().getTitle());
                }
                if (c.getUser() != null) {
                    dto.setUserId(c.getUser().getId());
                    dto.setUsername(c.getUser().getUsername());
                }
                pendingList.add(dto);
            } else if ("pending".equalsIgnoreCase(r.getStatus())) {
                pendingList.add(convertToDTO(r));
            }
        }

        // 手动分页
        int start = (int) Math.min(pageable.getOffset(), pendingList.size());
        int end = Math.min(start + pageable.getPageSize(), pendingList.size());
        List<ReviewDTO> pageContent = pendingList.subList(start, end);

        return new PageImpl<>(pageContent, pageable, pendingList.size());
    }

    @Override
    public void batchReview(List<Long> reviewIds, String status, String reason) {
        log.info("批量审核: {}, status: {}, reason: {}", reviewIds, status, reason);
        List<Review> reviews = reviewRepository.findAllById(reviewIds);
        LocalDateTime now = LocalDateTime.now();
        reviews.forEach(review -> {
            review.setStatus(status);
            review.setReviewComment(reason == null ? "" : reason);
            if (review.getId() == null) {
                review.setCreatedAt(now);
            }
            review.setUpdatedAt(now);
        });
        reviewRepository.saveAll(reviews);
    }

    @Override
    public ReviewDTO review(ReviewDTO reviewDTO) {
        if (reviewDTO == null) {
            throw new IllegalArgumentException("参数不能为空");
        }
        Long commentId = reviewDTO.getCommentId();
        String status = reviewDTO.getStatus();
        String reason = reviewDTO.getReviewComment();

        log.info("审核单个内容: commentId: {}, status: {}, reason: {}", commentId, status, reason);

        if (commentId == null) {
            throw new IllegalArgumentException("commentId 不能为空");
        }

        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new RuntimeException("评论不存在"));

        Review review = reviewRepository.findByCommentId(commentId).orElse(new Review());
        review.setComment(comment);
        review.setStatus(status);
        review.setReviewComment(reason);
        SysUser systemUser = userRepository.findById(reviewDTO.getReviewerId()).orElseThrow(() -> new RuntimeException("用户不存在"));
        review.setReviewer(systemUser);
        if (review.getId() == null) {
            review.setCreatedAt(LocalDateTime.now());
        }
        review.setUpdatedAt(LocalDateTime.now());
        Review saved = reviewRepository.save(review);
        return convertToDTO(saved);
    }

    @Override
    public ReviewDTO findById(Long reviewId) {
        log.info("获取审核详情: {}", reviewId);
        Review review = reviewRepository.findById(reviewId)
                .orElseThrow(() -> new RuntimeException("审核记录不存在"));
        return convertToDTO(review);
    }

    @Override
    public void delete(Long reviewId) {
        log.info("删除审核记录: {}", reviewId);
        if (!reviewRepository.existsById(reviewId)) {
            throw new RuntimeException("审核记录不存在");
        }
        reviewRepository.deleteById(reviewId);
    }

    @Override
    public Map<String, Object> getReviewStatistics() {
        log.info("获取审核统计");
        List<Review> reviews = reviewRepository.findAll();

        long totalReviews = reviews.size();
        long pendingReviews = reviews.stream()
                .filter(review -> "pending".equals(review.getStatus()))
                .count();
        long approvedReviews = reviews.stream()
                .filter(review -> "approved".equals(review.getStatus()))
                .count();
        long rejectedReviews = reviews.stream()
                .filter(review -> "rejected".equals(review.getStatus()))
                .count();

        return Map.of(
                "totalReviews", totalReviews,
                "pendingReviews", pendingReviews,
                "approvedReviews", approvedReviews,
                "rejectedReviews", rejectedReviews
        );
    }

    @Override
    public Map<String, Object> getCommentCount() {
        log.info("获取评论总数统计");
        // 这里需要查询评论表的总数
        // 暂时返回模拟数据
        return Map.of(
                "totalComments", 150,
                "pendingComments", 25,
                "approvedComments", 120,
                "rejectedComments", 5
        );
    }

    @Override
    public List<Map<String, Object>> getRecentActivities() {
        log.info("获取最近活动记录");
        // 这里需要查询最近的审核活动
        // 暂时返回空列表
        return List.of();
    }

    private ReviewDTO convertToDTO(Review review) {
        ReviewDTO dto = new ReviewDTO();
        dto.setId(review.getId());

        // 设置评论信息
        if (review.getComment() != null) {
            dto.setCommentId(review.getComment().getId());
            dto.setCommentContent(review.getComment().getContent());
            dto.setCommentRating(review.getComment().getRating());

            // 设置影片信息（通过评论关联）
            if (review.getComment().getMovie() != null) {
                dto.setMovieId(review.getComment().getMovie().getId());
                dto.setMovieTitle(review.getComment().getMovie().getTitle());
            }

            // 设置用户信息（通过评论关联）
            if (review.getComment().getUser() != null) {
                dto.setUserId(review.getComment().getUser().getId());
                dto.setUsername(review.getComment().getUser().getUsername());
            }
        }

        // 设置审核人信息
        if (review.getReviewer() != null) {
            dto.setReviewerId(review.getReviewer().getId());
            dto.setReviewerName(review.getReviewer().getUsername());
        }

        dto.setStatus(review.getStatus());
        dto.setReviewComment(review.getReviewComment());
        dto.setCreatedAt(review.getCreatedAt());
        dto.setUpdatedAt(review.getUpdatedAt());

        return dto;
    }
}